package com.opencee.cloud.msg.thread.handler;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.opencee.cloud.msg.api.entity.MsgEmailTemplateEntity;
import com.opencee.cloud.msg.api.entity.MsgTaskEmailRecordsEntity;
import com.opencee.cloud.msg.api.vo.MsgChannelConfigVO;
import com.opencee.cloud.msg.api.vo.params.EmailTextParams;
import com.opencee.cloud.msg.api.vo.params.EmailTplParams;
import com.opencee.cloud.msg.api.vo.params.MessageTaskParams;
import com.opencee.cloud.msg.config.MessageTaskContext;
import com.opencee.cloud.msg.service.MsgEmailTemplateService;
import com.opencee.cloud.msg.service.MsgTaskEmailRecordsService;
import com.opencee.cloud.msg.service.impl.email.EmailSenderServiceImpl;
import com.opencee.cloud.msg.thread.MessageTaskHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.util.Assert;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.dialect.IDialect;
import org.thymeleaf.spring5.dialect.SpringStandardDialect;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.StringTemplateResolver;

import java.util.Date;
import java.util.Map;
import java.util.Properties;

/**
 * 发送邮件适配器
 *
 * @author yadu
 */
@Slf4j
public class EmailTaskHandler implements MessageTaskHandler {

    private EmailSenderServiceImpl emailSenderService;
    private MsgEmailTemplateService msgEmailTemplateService;
    private MsgTaskEmailRecordsService msgTaskEmailDetailsService;
    private TemplateEngine templateEngine = new TemplateEngine();
    private StringTemplateResolver templateResolver = new StringTemplateResolver();

    public EmailTaskHandler() {
    }

    public EmailTaskHandler(EmailSenderServiceImpl emailSenderService, MsgEmailTemplateService msgEmailTemplateService, MsgTaskEmailRecordsService msgTaskEmailDetailsService) {
        this.emailSenderService = emailSenderService;
        this.msgEmailTemplateService = msgEmailTemplateService;
        this.msgTaskEmailDetailsService = msgTaskEmailDetailsService;
        this.templateResolver.setTemplateMode(TemplateMode.HTML);
        IDialect dialect = new SpringStandardDialect();
        this.templateEngine.setDialect(dialect);
        //创建StringTemplateResolver
        this.templateResolver.setCacheable(true);
        //引擎使用StringTemplateResolver
        this.templateEngine.setTemplateResolver(templateResolver);
    }


    /**
     * 前置参数验证
     *
     * @param taskParams
     * @return
     */
    @Override
    public boolean validate(MessageTaskContext context, MessageTaskParams taskParams) throws RuntimeException {
        Object params = taskParams.getParams();
        // 模板参数
        if (params instanceof EmailTplParams) {
            EmailTplParams tplParams = (EmailTplParams) params;
            Assert.notEmpty(tplParams.getTo(), "收件人不能为空");
            MsgEmailTemplateEntity template = msgEmailTemplateService.getByCode(tplParams.getTplCode());
            Assert.notNull(template, "模板信息不存在");
            context.setVariable("template", template);
        } else {
            // 文本参数
            EmailTextParams textParams = (EmailTextParams) taskParams.getParams();
            Assert.notEmpty(textParams.getTo(), "收件人不能为空");
            Assert.hasText(textParams.getSubject(), "标题不能为空");
            Assert.hasText(textParams.getContent(), "内容不能为空");
        }
        return true;
    }

    @Override
    public boolean execute(MessageTaskContext context, MessageTaskParams taskParams) {
        MsgChannelConfigVO config = taskParams.getChannelConfig();
        Object params = taskParams.getParams();
        String error = null;
        Boolean result = false;
        EmailTextParams textParams = new EmailTextParams();
        EmailTplParams tplParams = null;
        try {
            if (params instanceof EmailTplParams) {
                tplParams = (EmailTplParams) params;
                MsgEmailTemplateEntity template = (MsgEmailTemplateEntity) context.getVariable("template");
                String content = generateHtml(template.getContent(), tplParams.getTplParams());
                BeanUtils.copyProperties(tplParams, textParams);
                textParams.setContent(content);
            } else {
                BeanUtils.copyProperties(params, textParams);
            }
            // 构建发送者
            JavaMailSenderImpl javaMailSender = buildMailSender(config.getContentObject());
            emailSenderService.sendSimpleMail(javaMailSender, textParams);
            result = true;
        } catch (Exception e) {
            error = e.getMessage();
            log.error("发送错误:", e);
        } finally {
            // 保存发送日志
            MsgTaskEmailRecordsEntity record = new MsgTaskEmailRecordsEntity();
            record.setTaskId(taskParams.getTaskId());
            record.setSendTo(CollectionUtil.join(textParams.getTo(), ";"));
            if (!CollectionUtil.isEmpty(textParams.getCc())) {
                record.setSendCc(CollectionUtil.join(textParams.getCc(), ";"));
            }
            record.setTitle(textParams.getSubject());
            record.setContent(textParams.getContent());
            record.setError(error);
            record.setStatus(result ? 1 : 0);
            record.setTplCode(tplParams != null ? tplParams.getTplCode() : null);
            record.setAttachments(JSONObject.toJSONString(textParams.getAttachments()));
            record.setCreateTime(new Date());
            record.setUpdateTime(record.getCreateTime());
            msgTaskEmailDetailsService.save(record);
        }
        return result;
    }

    @Override
    public boolean support(Object message) {
        return message instanceof EmailTextParams || message instanceof EmailTplParams;
    }


    private JavaMailSenderImpl buildMailSender(JSONObject config) {
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setHost(config.getString("host"));
        sender.setUsername(config.getString("username"));
        sender.setPassword(config.getString("password"));
        sender.setPort(config.getIntValue("port"));
        sender.setDefaultEncoding("UTF-8");
        sender.setProtocol("smtp");
        Properties properties = new Properties();
        properties.putAll(config.getJSONObject("properties"));
        sender.setJavaMailProperties(properties);
        return sender;
    }


    public String generateHtml(String htmlTemplate, Map data) {
        Context context = new Context();
        context.setVariables(data);
        return this.templateEngine.process(htmlTemplate, context);
    }

}
